module GYLite
{
								
			
	export class GYGridBase extends GYGroup implements IList
	{
		protected _innerHeight:number;
		protected _innerWidth:number;
		protected _cols:number;
		protected _rows:number;
		protected _paddingR:number;
		protected _paddingB:number;
		protected _dataProvider:Array<any>;
		protected _grids:Array<any>;
		protected _boxW:number;
		protected _boxH:number;
		protected createGrid:Function;
		protected setGridData:Function;
		protected _lastLine:number;
		protected _lastEndLine:number;
		protected _max:number;
		protected _scrollerPolicy:number;
		protected _gridUpdate:boolean;
		protected _dataUpdate:boolean;
		protected _boxNumUpdate:boolean;
		protected _boxNumUpdateReset:boolean;
//		/**格子的尺寸、间隔改变*/protected _gridSizeChange:boolean;
		protected _canSelectNum:number;
		protected _selectList:any[];
		protected _selectedData:any;
		protected _selectIndex:number;
		protected _keepSelected:boolean;
		protected _dataToItemDict:Dictionary;
		protected _nextData:any;
		protected _selectMode:number;
		protected _wheelScroll:boolean;
		protected _wheelStep:number;
		protected _stopSelTarget:any;
		private _selectTime:number;
		private _selectInterval:number;
		protected _dragSelect:boolean;
		protected _mouseSelect:boolean;
		protected _addSelect:boolean;
		protected _getThisObject:any;
		protected _setThisObject:any;
		protected _virtual_layout:boolean;
		protected _scrollPosLimit:number;
		protected _scrollToPos:number;
		protected _overlying:boolean;
		/**速度系数，乘以滑动的速度*/public speedParam:number;
		/**区间限制的时候，恢复到区间位置的滚动花费时间*/public scrollNextTime:number;
		/**Grid组件基类，请继承自定义其逻辑，或者使用GYGrid GYGridV GYGridH
		 * @param sizeW Grid宽度 设定后无法更，当为负数的时候则表示为列数cols，此时则需要另外设置Grid宽和项宽（s.boxW）
		 * @param sizeH Grid高度 设定后无法更，当为负数的时候则表示为行数rows，此时则需要另外设置Grid高和项高（s.boxH）
		 * @param getGridFunc():IItemRender 返回自定义格子对象的方法 
		 * @param setGridFunc(IItemRender, any) 设置格子数据的方法*/
		public constructor(sizeW:number,sizeH:number,getGridFunc:Function=null, getThisObject:any=null, setGridFunc:Function=null, setThisObject:any=null)
		{
			super();
			var s = this;
			if(sizeW * sizeH < 0)
			{
				throw(new Error("sizeW和sizeH必须同时大于0或者小于0"));				
			}
			s.speedParam = 1;
			s.scrollNextTime = NaN;
			s._overlying = true;
			s._scrollPosLimit = NaN;
			s._cols=sizeW;
			s._rows=sizeH;
			s.createGrid=getGridFunc;
			s.setGridData=setGridFunc;
			s._getThisObject = getThisObject;
			s._setThisObject = setThisObject;
			s.virtual_layout = true;			
			s.initComponent();
		}
		protected initComponent():void
		{var s = this;
			s._innerHeight=NaN;
			s._innerWidth=NaN;			
			s._paddingR=0;
			s._paddingB=0;
			s._dataProvider=null;			
			s._boxW=0;
			s._boxH=0;					
			s._max=0;
			s._scrollerPolicy=0;
			s._gridUpdate=false;
			s._dataUpdate=false;	
			s._canSelectNum=0;
			s._selectList=null;
			s._selectedData=null;			
			s._keepSelected=false;
			s._dataToItemDict=null;
			s._nextData=null;
			s._selectMode=0;					
			s._stopSelTarget=null;
			s._selectTime=NaN;			
			s._dragSelect=false;
			s._mouseSelect=false;
			s._addSelect=false;

			s._lastEndLine = s._lastLine=0;
			s._selectInterval = GYGridBase.default_selectInterval;
			s._wheelStep = GYGridBase.default_wheelStep;
			s.wheelScroll = GYGridBase.default_wheelScroll;
			s._selectIndex = -1;
			this.clipAndEnableScrolling = true;
			s._grids = [];
		}
		protected getGrid():IItemRender
		{var s = this;
			var item:IItemRender;
			if(s.createGrid!=null)
				item = s.createGrid.call(s._getThisObject);
			else
				item = new ItemRender;
			if(s._dragSelect)
			{
				item.addEventListener(egret.TouchEvent.TOUCH_BEGIN, s.selectCell, s);
				item.addEventListener(MouseEvent.ROLL_OVER, s.selectCell, s);
			}
			else
				item.addEventListener(egret.TouchEvent.TOUCH_TAP, s.selectCell, s);
			item.owner = this;
			return item;
		}
		protected setGrid(grid:IItemRender, obj:any):void
		{var s = this;
			var d:any = grid.getData();
			if(s._dataToItemDict)
			{
				if(s._dataToItemDict.getValue(d) == grid)
					s._dataToItemDict.deleteKey(d);
				if(obj)
					s._dataToItemDict.setValue(obj, grid);
			}
			if(s.dataIsSelected(obj))
			{
				if(!grid.selected)grid.selected = true;
			}
			else
				if(grid.selected)grid.selected = false;
			if(s.setGridData != null)
				s.setGridData.call(s._setThisObject, grid,obj);
			else
				grid.setData(obj);
		}
		protected selectCell(e:egret.TouchEvent):void
		{var s = this;
			if(s._stopSelTarget == e.target)
			{
				s._stopSelTarget = null;
				return;
			}
			if(s._canSelectNum == 0)
				return;
			var item:IItemRender = e.currentTarget as IItemRender;
			var stInd:number,endInd:number;
			var ind:number;
			var i:number,j:number,len:number,add:number;
			var isFind:boolean;
			var tempItem:IItemRender;
			var data:any,tempData:any;
			var end:number;
			var tempVec:any[];
			if(s._dragSelect)
			{				
				if(e.type == "rollOver" && !GYSprite.isStageDown(s) || !e.touchDown)	
					return;
				GYSprite.addStageDown(s, s.releaseOutSide, s);
				s.addEventListener(MouseEvent.ROLL_OUT, s.selectOut,s);
				s.addEventListener(MouseEvent.ROLL_OVER, s.selectIn,s);
				s.addEventListener(egret.TouchEvent.TOUCH_END,s.releaseOutSide,s);
			}
			if(s._canSelectNum > 1)
			{
				data = item.getData();				
				if((e.type == "rollOver" || GYKeyboard.getInstance().isShiftDown()) && s._selectedData)
				{
					if(data)
					{
						s._mouseSelect = true;
						s.selectLine(data,s._selectedData,GYKeyboard.getInstance().isCtrlDown());
					}
					return;
				}
				else if(GYKeyboard.getInstance().isCtrlDown())
				{
					if(data)
					{	
						ind = s._selectList.indexOf(data);
						if(ind == -1)
						{
							if(s._canSelectNum <= s._selectList.length)
								return;
							s._selectList.push(data);
							item.selected = true;
						}
						else
						{
							s._selectList.splice(ind,1);
							item.selected = false;
						}
					}
					s._addSelect = true;
				}
				else
				{
					len = s._selectList.length;
					while(--len>-1)
					{
						if(s._selectList[len] == data)
						{
							isFind = true;
							continue;
						}
						tempItem = s.dataToItemDict.getValue(s._selectList[len]);
						if(tempItem)
						{
							tempItem.selected = false;
						}
					}
					s._selectList.length = 0;
					s._selectList.push(data);
					if(!isFind && s.dataToItemDict.getValue(data))
						s.dataToItemDict.getValue(data).selected = true;
				}
			}
			s._mouseSelect = true;
			s.selectedItem = item;
		}
		protected selectLine(data:any,selectedData:any,ctrlKey:boolean,checkNext:boolean=false):void
		{var s = this;
		}
		/**跳转至某索引项*/
		public scrollToIndex(val:number):void
		{var s = this;
			
		}
		/**跳转到row行col列(位置在末尾)*/
		public scrollToEndIndex(val:number):void
		{var s = this;
		}
		protected selectIn(e:egret.TouchEvent):void
		{var s = this;
			CommonUtil.delStageLoop(s.selectLoop,s);
		}
		protected selectOut(e:egret.TouchEvent):void
		{var s = this;
			s._selectTime = egret.getTimer();
			CommonUtil.addStageLoop(s.selectLoop,s);
		}
		private selectLoop(t:number):void
		{var s = this;
			if(t - s._selectTime > s._selectInterval)
			{
				s._selectTime = t;
				s._mouseSelect = true;
				s.selectLine(s._nextData, s._selectedData, false, true);
			}
		}
		public dataIsSelected(d:any):boolean
		{var s = this;
			if(d == null)return false;
			if(s.canSelectNum == 1)
			{
				return s._selectedData == d;
			}
			if(s.canSelectNum > 1)
			{
				return s._selectList.length > 0?s._selectList.indexOf(d) > -1:false;
			}
			return false;
		}
		protected releaseOutSide(e:egret.TouchEvent):void
		{var s = this;
			CommonUtil.delStageLoop(s.selectLoop,s);
			s.removeEventListener(MouseEvent.ROLL_OUT, s.selectOut,s);
			s.removeEventListener(MouseEvent.ROLL_OVER, s.selectIn,s);
		}
		public set boxW(val:number)
		{var s = this;
			s._boxW=val;
//			s._gridSizeChange = true;
			s.invalidGrids();
		}
		public set boxH(val:number)
		{var s = this;
			s._boxH=val;
//			s._gridSizeChange = true;
			s.invalidGrids();
		}
		public set paddingR(val:number)
		{var s = this;
			s._paddingR=val;
//			s._gridSizeChange = true;
			s.invalidGrids();
		}
		public set paddingB(val:number)
		{var s = this;
			s._paddingB=val;
//			s._gridSizeChange = true;
			s.invalidGrids();
		}
		/**格子宽度*/
		public get boxW():number
		{var s = this;
			return s._boxW;
		}
		/**格子高度*/
		public get boxH():number
		{var s = this;
			return s._boxH;
		}
		/**格子右边间隙*/
		public get paddingR():number
		{var s = this;
			return s._paddingR;
		}
		/**格子底边间隙*/
		public get paddingB():number
		{var s = this;
			return s._paddingB;
		}
		public set dataProvider(val:Array<any>)
		{var s = this;
			s._dataProvider =val;
		}
		/**数据源*/
		public get dataProvider():Array<any>
		{var s = this;
			return s._dataProvider;
		}
		set rows(val)
		{
			this._rows = val;
		}
		get rows()
		{
			return this._rows;
		}
		set cols(val)
		{
			this._rows = val;
		}
		get cols()
		{
			return this._cols;
		}
		set virtual_layout(val)
		{let s= this;
			if(s._virtual_layout == val)return;
			s._virtual_layout = val;
			s.outSideOptimize = !val;
			if(s._dataProvider)
			{
				s.rows = s._cols > 0?Math.ceil(s._dataProvider.length / s._cols):0;
			}
		}
		get virtual_layout()
		{
			return this._virtual_layout;
		}
		public set canSelectNum(val:number)
		{var s = this;
			if(val > 0)
			{
				s.dataToItemDict;
			}
			else
			{
				s.selectedItem = null;
				if(s._selectList)
					s._selectList.length = 0;
				s.invalidData();
			}
			
			s._canSelectNum = val;
		}
		/**允许选择多少项(默认0，不能选择)*/
		public get canSelectNum():number
		{var s = this;
			return s._canSelectNum;
		}
		/**选中项的数据列表(当s.canSelectNum大于1时，将会提供此选择列表)*/
		public get selectList():any[]
		{var s = this;
			return s._selectList;
		}
		public set selectList(val:any[])
		{var s = this;
			let i:number,len:number;
			if(s._canSelectNum < 1)return;
			if(s._selectList && s._selectList.length > 0)
			{
				len = s._selectList.length;
				for(i=0;i<len;++i)
				{
					if(s._selectList[i])
					{
						s._selectIndex = -1;
						s._selectedData = null;
						if(s._selectList[i] && s.dataToItemDict.getValue(s._selectList[i]))
							s.dataToItemDict.getValue(s._selectList[i]).selected = false;
					}
				}	
				s._selectList.length = 0;
			}						
			if(val)
			{
				len = val.length;
				for(i=0;i<len;++i)
				{
					if(val[i])
						s.selectedData = val[i];
				}
			}			
		}
		/**选择的数据索引*/
		public get selectedIndex():number
		{var s = this;
			return s._selectIndex;
		}
		public set selectedIndex(val:number)
		{var s = this;
			var len:number;
			if(s.canSelectNum < 1)return;
			if(s._selectIndex == val)return;
			if(val >= s._dataProvider.length)return;
			if(val < 0)return;
			s._selectIndex = val;
			s.selectedData = s._dataProvider[val];
		}	
		public set selectedItem(val:IItemRender)
		{var s = this;
			var oldData:any;
			oldData = s._selectedData;
			s._nextData = s._selectedData = val?val.getData():null;
			if(!s._addSelect && oldData && oldData != s._selectedData && s.dataToItemDict.getValue(oldData))
				s.dataToItemDict.getValue(oldData).selected = false;
			if(val == null || val.getData() == null)
			{
				if(s._selectList)s._selectList.length = 0;
				s._selectIndex = -1;
			}
			else
			{
				s._selectIndex = s.dataToItemDict.getValue(s._selectedData).itemIndex;
				if(!s._addSelect)
					val.selected = true;
			}
			s._addSelect = false;
			if(s.hasEventListener(GYViewEvent.SELECTED) && s._mouseSelect)
			{
				s.dispatchEvent(new GYViewEvent(GYViewEvent.SELECTED));
				s._mouseSelect = false;
			}
		}
		/**当前选择的ItemRender*/
		public get selectedItem():IItemRender
		{var s = this;
			return s.dataToItemDict.getValue(s._selectedData);
		}
		public set selectedData(d:any)
		{var s = this;
			if(s._canSelectNum == 0)return;
			if(s._selectedData == d)return;
			var oldData:any;
			oldData = s._selectedData;
			s._selectedData = d;
			if(s.canSelectNum > 1)
			{
				var ind:number = s._selectList.indexOf(s._selectedData);
				if(ind == -1)
				{
					s._selectList.push(s._selectedData);
				}
			}
			else if(oldData && s.dataToItemDict.getValue(oldData))
			{
				s.dataToItemDict.getValue(oldData).selected = false;
			}
			s._selectIndex = d == null?-1:(CommonUtil.GYIs(s.dataToItemDict.getValue(d),"GYLite.IItemRender")?s.dataToItemDict.getValue(d).itemIndex:-1);
			if(s._selectedData && s.dataToItemDict.getValue(s._selectedData))
				s.dataToItemDict.getValue(s._selectedData).selected = true;
		}
		/**当前选择的数据，选择的数据不一定与选择的项相对应，由于内部使用的是渲染项循环滚动以节省资源，所以滚动之后ItemRender的数据不一定就是选择的数据*/
		public get selectedData():any
		{var s = this;
			return s._selectedData;
		}
		/**数据失效*/
		public invalidData():void
		{var s = this;
			if(s._dataUpdate)
				return;
			s._dataUpdate = true;
			s.displayChg();
		}

		/**格子数量失效*/
		public invalidBoxNum():void
		{var s = this;
			if(s._boxNumUpdate)
				return;
			s._boxNumUpdate = true;
			s.displayChg();
		}
		
		/**网格失效*/
		public invalidGrids():void
		{var s = this;
			if(s._gridUpdate)
				return;
			s._gridUpdate = true;
			s.displayChg();
		}
		/**刷新格子布局*/
		public updateGrid():void
		{var s = this;
			
		}
		/**刷新数据*/
		public updateData():void
		{var s = this;
			s.dataProvider = s._dataProvider;
		}
		/**移除索引位置上的数据项（刷新）*/
		public removeItemAt(ind:number):void
		{var s = this;
			if(ind < s._dataProvider.length)
			{
				s._dataProvider.splice(ind, 1);
				s.updateData();
			}
		}
		/**移除数据项（刷新）*/
		public removeItem(d:any):void
		{var s = this;
			var ind:number = s._dataProvider.indexOf(d);
			if(ind > -1)
			{
				s._dataProvider.splice(ind, 1);
				s.updateData();
			}
		}
		/**添加索引位置数据项（刷新）*/
		public addItemAt(d:any, ind:number):void
		{var s = this;
			if(ind <= s._dataProvider.length)
			{
				s._dataProvider.splice(ind,0,d);
				s.updateData();
			}
		}
		/**添加数据项（刷新）*/
		public addItem(d:any):void
		{var s = this;
			s._dataProvider.push(d);
			s.updateData();
		}
		/**刷新数据项*/
		public updateItem(d:any):void
		{var s = this;
			if(s.dataToItemDict.getValue(d))
				(s.dataToItemDict.getValue(d) as IItemRender).setData(d);
		}
		/**刷新格子数*/
		protected boxNumChange(update:boolean=false):void
		{
			
		}
		/**刷新列表可见的所有项*/
		public updateItems():void
		{
			
		}
		/**@inheritDoc*/
		public updateView():void
		{var s = this;
			if(s._boxNumUpdate)
			{
				s.boxNumChange(s._boxNumUpdateReset);
				s._boxNumUpdateReset = s._boxNumUpdate = false;
			}
			if(s._dataUpdate)
			{
				s.updateData();
				if(s.hasEventListener(GYEvent.VALUE_COMMIT))
					s.dispatchEvent(new GYEvent(GYEvent.VALUE_COMMIT));
				s._dataUpdate = false;
			}			
			if(s._gridUpdate)
			{
				s.updateGrid();
//				s._gridSizeChange = false;
				s._gridUpdate = false;
			}			
			super.updateView();
		}

		/**拖选的选择模式，0为行列矩阵的拖选，1逐行或者逐列的拖选，可重写s.selectLine方法自定义拖选规则*/
		public get selectMode():number
		{var s = this;
			return s._selectMode;
		}
		public set selectMode(val:number)
		{var s = this;
			s._selectMode = val;
		}
		/**拖选时的滚动时间间隔(毫秒)*/
		public get selectInterval():number
		{var s = this;
			return s._selectInterval;
		}
		public set selectInterval(val:number)
		{var s = this;
			s._selectInterval = val;
		}
		/**是否启用拖选功能*/
		public get dragSelect():boolean
		{var s = this;
			return s._dragSelect;
		}

		public set dragSelect(value:boolean)
		{var s = this;
			s._dragSelect = value;
			var len:number;
			var item:IItemRender;
			len = s._grids.length;
			while(--len>-1)
			{
				item = s._grids[len];
				if(s._dragSelect)
				{
					item.removeEventListener(egret.TouchEvent.TOUCH_TAP, s.selectCell, s);
					item.addEventListener(egret.TouchEvent.TOUCH_BEGIN, s.selectCell, s);
					item.addEventListener(MouseEvent.ROLL_OVER, s.selectCell, s);
				}
				else
				{
					item.removeEventListener(egret.TouchEvent.TOUCH_BEGIN, s.selectCell, s);
					item.removeEventListener(MouseEvent.ROLL_OVER, s.selectCell, s);
					item.addEventListener(egret.TouchEvent.TOUCH_TAP, s.selectCell, s);
				}
			}
		}

		public get stopSelTarget():any
		{var s = this;
			return s._stopSelTarget;
		}

		public set stopSelTarget(value:any)
		{var s = this;
			s._stopSelTarget = value;
		}
		/**是否保留选择的数据项*/
		public get keepSelected():boolean
		{var s = this;
			return s._keepSelected;
		}

		public set keepSelected(value:boolean)
		{var s = this;
			s._keepSelected = value;
		}

		public get innerWidth():number
		{var s = this;
			return s._innerWidth;
		}

		public get innerHeight():number
		{var s = this;
			return s._innerHeight;
		}
		/**连选时末尾选中的数据*/
		public get nextData():any
		{var s = this;
			return s._nextData;
		}

		public get wheelStep():number
		{var s = this;
			return s._wheelStep;
		}

		public set wheelStep(value:number)
		{var s = this;
			s._wheelStep = value;
		}
		/**是否启用滚轮*/
		public get wheelScroll():boolean
		{var s = this;
			return s._wheelScroll;
		}

		public set wheelScroll(value:boolean)
		{var s = this;
			s._wheelScroll = value;
			if(s._wheelScroll)			
				s.setWheelFunc(s.wheelRoll,s);						
			else		
				s.setWheelFunc(null);		
		}

		protected wheelRoll(e:egret.TouchEvent):void
		{var s = this;
			
		}

		public get dataToItemDict():Dictionary
		{var s = this;
			if(s._dataToItemDict==null)
			{
				s._selectList = [];
				s._dataToItemDict = new Dictionary();
				var len:number = s._grids.length;
				while(--len>-1)
				{
					var obj:any = s._grids[len].getData();
					if(obj)
						s._dataToItemDict.setValue(obj, s._grids[len]);
				}
			}
			return s._dataToItemDict;
		}
		/**滚动区间限制,限制滚动停止的位置以相等的距离*/
		public set scrollPosLimit(val:number)
		{let s = this;
			s._scrollPosLimit = val;
		}
		public get scrollPosLimit():number
		{let s = this;
			return s._scrollPosLimit;
		}
		/**滚动条 0自动 1显示 2不显示*/
		public set scrollerPolicy(val:number)
		{
		}
		public get scrollerPolicy():number
		{
			return 0;
		}
		/**滚动到下一项
		 * @return 返回滚动的目标位置
		*/
		public scrollToNextItem():number
		{
			return 0;
		}
		/**滚动到上一项
		 * @return 返回滚动的目标位置
		*/
		public scrollToPreItem():number
		{
			return 0;
		}
		protected scrollEnd(e:GYScrollerEvent=null):void
		{
			
		}
		/**scrollToNextItem、scrollToPreItem是否叠加滚动，默认true*/
		public get overlying():boolean
		{
			return this._overlying;
		}
		public set overlying(val:boolean)
		{
			this._overlying = val;
		}
		
		/**拖选响应毫秒(默认值)*/public static default_selectInterval:number = 50;
		/**滚轮步长(默认值)*/public static default_wheelStep:number=0;
		/**是否允许滚轮(默认值)*/public static default_wheelScroll:boolean = true;
	}
}